﻿using mesan.core.Managers;
using mesan.core.Repository;
using mesan.crosscutting.testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Should;

namespace mesan.core.unittests.Managers
{
	[TestClass]
	public class LoginManagerTests : BasedOn<LoginManager>
	{
		[TestMethod]
		public void RequestPasswordReset_EmailIsEmpty_DoesNotSendAnything()
		{
			// Arrange
			var emptyEmail = string.Empty;

			// Act
			Instance.RequestPasswordReset(emptyEmail);

			// Assert
			EmailShouldNotHaveBeenSent();
		}

		[TestMethod]
		public void RequestPasswordReset_EmailHasValue_SendsEmail()
		{
			// Arrange
			var email = "pedro@digitaldias.com";

			// Act
			Instance.RequestPasswordReset(email);

			// Assert
			EmailShouldHaveBeenSent();
		}

		[TestMethod]
		public void RequestPasswordReset_EmailIsNotValid_DoesNotSendEmail()
		{
			// Arrange
			var invalidEmail = RandomString;

			// Act
			Instance.RequestPasswordReset(invalidEmail);

			// Assert
			EmailShouldNotHaveBeenSent();
		}

		[TestMethod]
		public void Validate_UsernameAndPasswordMissing_ResultIsFalse()
		{
			// Arrange
			var emptyUserName = string.Empty;
			var emptyPassword = string.Empty;

			// Act	
			var result = Instance.Validate(emptyUserName, emptyPassword);

			// Assert
			result.ShouldBeFalse();
		}

		[TestMethod]
		public void Validate_UsernameAndPasswordHaveValues_InvokesValidationRepository()
		{
			// Arrange
			var userName = RandomString;
			var password = RandomString;

			// Act	
			var result = Instance.Validate(userName, password);

			// Assert
			GetMockFor<IValidationRepository>()
				.Verify(o => o.Validate(userName, password), Times.Once());
		}

		[TestMethod]
		public void Validate_UsernameIsSetButPasswordIsEmpty_ResultIsFalse()
		{
			// Arrange
			var username      = RandomString;
			var emptyPassword = string.Empty;

			// Act	
			var result = Instance.Validate(username, emptyPassword);

			// Assert
			result.ShouldBeFalse();
		}

		[TestMethod]
		public void Validate_UsernameIsBlankButPasswordIsSet_ResultIsFalse()
		{
			// Arrange
			var emptyUsername = string.Empty;
			var password = RandomString;

			// Act	
			var result = Instance.Validate(emptyUsername, password);

			// Assert
			result.ShouldBeFalse();
		}

		[TestMethod]
		public void Validate_EmptyUsernameOrEmptyPassword_DoesNotInvokeRepository()
		{
			// Arrange
			var userName      = RandomString;
			var password      = RandomString;
			var emptyUserName = string.Empty;
			var emptyPassword = string.Empty;

			// Act	
			Instance.Validate(emptyUserName, password);
			Instance.Validate(userName, emptyPassword);

			// Assert
			GetMockFor<IValidationRepository>()
				.Verify(o => o.Validate(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
		}

		private void EmailShouldHaveBeenSent()
		{
			GetMockFor<IPasswordRequester>().Verify(o => o.RequestByEmail(It.IsAny<string>()), Times.Once());
		}

		private void EmailShouldNotHaveBeenSent()
		{
			GetMockFor<IPasswordRequester>().Verify(o => o.RequestByEmail(It.IsAny<string>()), Times.Never());
		}
	}
}
